﻿using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using Service.Core.Identity.Model;
using Service.Core.Redis.Services;
using Service.Framework;
using Service.Framework.Packet;
using Service.Framework.Utils;

namespace Service.Core.Identity
{


    public class ClientService : IScopedService
    {
        private readonly HttpClient _httpClient;
        private readonly IRedisService _redisService;

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly AppSettings<IdsServiceConfigure> _appSettings;

        public ClientService(
            HttpClient httpClient, IRedisService redisService,
            AppSettings<IdsServiceConfigure> appSettings, IHttpContextAccessor httpContextAccessor)
        {
            this._httpClient = httpClient;
            this._redisService = redisService;
            this._appSettings = appSettings;
            this._httpContextAccessor = httpContextAccessor;
            CopyRequestHeadersToHttpClient(_httpClient,_httpContextAccessor);
           
        }

        public async Task<string> GetAccessToken()
        {
            var key = DefaultRedisKeys.ClientTokenKey + _appSettings.Instance.IdsConfig.ClientId;
            var token = await _redisService.Database.StringGetAsync(key);
            if (token.HasValue)
                return token;

            var config = new DiscoveryDocumentRequest()
            {
                Address = _appSettings.Instance.IdsConfig.Authority,
            };
            config.Policy = new DiscoveryPolicy() { RequireHttps = false };
            // 获取IDS4发现文档
            var disco = await _httpClient.GetDiscoveryDocumentAsync(config);
            if (disco.IsError)
            {
                throw new LogicErrorException($"IDS4服务器无法访问：{disco.Error}");
            }
            var tokenResponse = await _httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                //配置客户端信息
                Address = disco.TokenEndpoint,//获取token的地址
                ClientId = _appSettings.Instance.IdsConfig.ClientId,//客户端ID
                ClientSecret = _appSettings.Instance.IdsConfig.Secret,//客户端密钥
            });

            if (tokenResponse.IsError)
            {
                throw new LogicErrorException($"获取AccessToke错误：{tokenResponse.ErrorDescription}");
            }
            await _redisService.Database.StringSetAsync(key, tokenResponse.AccessToken, TimeSpan.FromSeconds(tokenResponse.ExpiresIn - 60));
            return tokenResponse.AccessToken;
        }

        public async Task<CustomTokenResponse> GetAccessTokenByPasswordToken(CustomPasswordTokenRequest passwordTokenRequest)
        {
            var config = new DiscoveryDocumentRequest()
            {
                Address = _appSettings.Instance.IdsConfig.Authority,
            };
            config.Policy = new DiscoveryPolicy() { RequireHttps = false };
            // 获取IDS4发现文档
            var disco = await _httpClient.GetDiscoveryDocumentAsync(config);
            if (disco.IsError)
            {
                throw new LogicErrorException($"IDS4服务器无法访问：{disco.Error}");
            }
            var tokenResponse = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest()
            {
                Address = disco.TokenEndpoint,
                ClientId = passwordTokenRequest.ClientId,
                ClientSecret = passwordTokenRequest.ClientSecret,
                GrantType = passwordTokenRequest.GrantType,
                UserName = passwordTokenRequest.UserName,
                Password = passwordTokenRequest.Password,
            });

            if (tokenResponse.IsError)
            {
                var code = StatusCode.KnowException;
                if (tokenResponse.Raw.Contains("code"))
                {
                    JObject json = JObject.Parse(tokenResponse.Raw);
                    if (Enum.TryParse<StatusCode>(json["code"].ToString(), out StatusCode result))
                    {
                        code = result;
                    }
                }
                var raw = tokenResponse.Raw;

                var errorMsg = tokenResponse.ErrorDescription;
                if (errorMsg.IsNullOrWhiteSpace())
                {
                    errorMsg = tokenResponse.Error;
                }

                throw new LogicErrorException($"{errorMsg}", code);
            }
            return new CustomTokenResponse(tokenResponse.AccessToken, tokenResponse.ExpiresIn, tokenResponse.TokenType, tokenResponse.RefreshToken, true);
        }

        public async Task<CustomTokenResponse> GetAccessTokenByRefreshToken(CustomRefreshTokenRequest customRefreshTokenRequest)
        {

            var config = new DiscoveryDocumentRequest()
            {
                Address = _appSettings.Instance.IdsConfig.Authority,
            };
            config.Policy = new DiscoveryPolicy() { RequireHttps = false };
            // 获取IDS4发现文档
            var disco = await _httpClient.GetDiscoveryDocumentAsync(config);
            if (disco.IsError)
            {
                throw new LogicErrorException($"IDS4服务器无法访问：{disco.Error}");
            }
            var tokenResponse = await _httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest()
            {
                Address = disco.TokenEndpoint,
                ClientId = customRefreshTokenRequest.ClientId,
                ClientSecret = customRefreshTokenRequest.ClientSecret,
                GrantType = customRefreshTokenRequest.GrantType,
                RefreshToken = customRefreshTokenRequest.RefreshToken,
            });
            if (tokenResponse.IsError)
            {
                var code = StatusCode.KnowException;
                if (tokenResponse.Raw.Contains("code"))
                {
                    JObject json = JObject.Parse(tokenResponse.Raw);
                    if (Enum.TryParse<StatusCode>(json["code"].ToString(), out StatusCode result))
                    {
                        code = result;
                    }
                }
                var raw = tokenResponse.Raw;

                var errorMsg = tokenResponse.ErrorDescription;
                if (errorMsg.IsNullOrWhiteSpace())
                {
                    errorMsg = tokenResponse.Error;
                }

                throw new LogicErrorException($"{errorMsg}", code);
            }
            return new CustomTokenResponse(tokenResponse.AccessToken, tokenResponse.ExpiresIn, tokenResponse.TokenType, tokenResponse.RefreshToken, true);
        }



        public async Task<CustomTokenResponse> GetAccessTokenBySms(CustomSmsTokenRequest customSmsTokenRequest)
        {

            var config = new DiscoveryDocumentRequest()
            {
                Address = _appSettings.Instance.IdsConfig.Authority,
            };
            config.Policy = new DiscoveryPolicy() { RequireHttps = false };
            // 获取IDS4发现文档
            var disco = await _httpClient.GetDiscoveryDocumentAsync(config);
            if (disco.IsError)
            {
                throw new LogicErrorException($"IDS4服务器无法访问：{disco.Error}");
            }
            var pairs = new Parameters
            {
                { "client_id", customSmsTokenRequest.ClientId },
                { "grant_type", customSmsTokenRequest.GrantType },
                { "client_secret", customSmsTokenRequest.ClientSecret },
                { "phone", customSmsTokenRequest.Phone },
                { "code", customSmsTokenRequest.Code }
            };
            var tokenResponse = await _httpClient.RequestTokenRawAsync(disco.TokenEndpoint, pairs);

            if (tokenResponse.IsError)
            {
                var code = StatusCode.KnowException;
                if (tokenResponse.Raw.Contains("code"))
                {
                    JObject json = JObject.Parse(tokenResponse.Raw);
                    if (Enum.TryParse<StatusCode>(json["code"].ToString(), out StatusCode result))
                    {
                        code = result;
                    }
                }
                var raw = tokenResponse.Raw;

                var errorMsg = tokenResponse.ErrorDescription;
                if (errorMsg.IsNullOrWhiteSpace())
                {
                    errorMsg = tokenResponse.Error;
                }

                throw new LogicErrorException($"{errorMsg}", code);
            }
            return new CustomTokenResponse(tokenResponse.AccessToken, tokenResponse.ExpiresIn, tokenResponse.TokenType, tokenResponse.RefreshToken, true);
        }


        public void CopyRequestHeadersToHttpClient(HttpClient httpClient, IHttpContextAccessor httpContextAccessor)
        {
            if (httpContextAccessor.HttpContext == null)
            {
                // 如果没有HttpContext，则直接返回。
                return;
            }

            var requestHeaders = httpContextAccessor.HttpContext.Request.Headers;

            foreach (var header in requestHeaders)
            {
                // 过滤掉一些不应该被转发的头，例如Host，Content-Length等。
                if (header.Key.ToLower() == "host" || header.Key.ToLower() == "content-length")
                {
                    continue;
                }
                if (!httpClient.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value.AsEnumerable()))
                {
                    // 处理添加请求头失败的情况（例如，重复的请求头）
                    // 可以选择记录日志或抛出异常
                }
            }
        }


    }
}
